home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / rcs4 / source / rcsgen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-08  |  13.2 KB  |  348 lines

  1. /*
  2.  *                     RCS revision generation
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcsgen.c 5.2 90/07/15 11:33:58 ROOT_DOS Release $ Purdue CS";
  6. #endif
  7.  
  8. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  9.    Distributed under license by the Free Software Foundation, Inc.
  10.  
  11. This file is part of RCS.
  12.  
  13. RCS is free software; you can redistribute it and/or modify
  14. it under the terms of the GNU General Public License as published by
  15. the Free Software Foundation; either version 1, or (at your option)
  16. any later version.
  17.  
  18. RCS is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. GNU General Public License for more details.
  22.  
  23. You should have received a copy of the GNU General Public License
  24. along with RCS; see the file COPYING.  If not, write to
  25. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  
  27. Report problems and direct all questions to:
  28.  
  29.     rcs-bugs@cs.purdue.edu
  30.  
  31. */
  32.  
  33.  
  34.  
  35. /* $Log:    rcsgen.c $
  36.  * Revision 5.2  90/07/15  11:33:58  ROOT_DOS
  37.  * checked in with -k by ROOT_DOS at 91.02.07.11.45.28.
  38.  * 
  39.  * Revision 5.2  90/07/15  11:33:58  ROOT_DOS
  40.  * DOS version of RCS 4.0 checked in for MODS
  41.  * by lfk@athena.mit.edu
  42.  * Also update to MSC 6.0
  43.  * 
  44.  * Revision 4.7  89/05/01  15:12:49  narten
  45.  * changed copyright header to reflect current distribution rules
  46.  * 
  47.  * Revision 4.6  88/11/08  12:01:13  narten
  48.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  49.  * 
  50.  * Revision 4.6  88/08/28  14:59:10  eggert
  51.  * Shrink stdio code size; allow cc -R; remove lint; isatty() -> ttystdin()
  52.  * 
  53.  * Revision 4.5  87/12/18  11:43:25  narten
  54.  * additional lint cleanups, and a bug fix from the 4.3BSD version that
  55.  * keeps "ci" from sticking a '\377' into the description if you run it
  56.  * with a zero-length file as the description. (Guy Harris)
  57.  * 
  58.  * Revision 4.4  87/10/18  10:35:10  narten
  59.  * Updating version numbers. Changes relative to 1.1 actually relative to
  60.  * 4.2
  61.  * 
  62.  * Revision 1.3  87/09/24  13:59:51  narten
  63.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  64.  * warnings)
  65.  * 
  66.  * Revision 1.2  87/03/27  14:22:27  jenkins
  67.  * Port to suns
  68.  * 
  69.  * Revision 1.1  84/01/23  14:50:28  kcs
  70.  * Initial revision
  71.  * 
  72.  * Revision 4.2  83/12/02  23:01:39  wft
  73.  * merged 4.1 and 3.3.1.1 (clearerr(stdin)).
  74.  * 
  75.  * Revision 4.1  83/05/10  16:03:33  wft
  76.  * Changed putamin() to abort if trying to reread redirected stdin.
  77.  * Fixed getdesc() to output a prompt on initial newline.
  78.  * 
  79.  * Revision 3.3.1.1  83/10/19  04:21:51  lepreau
  80.  * Added clearerr(stdin) for re-reading description from stdin.
  81.  * 
  82.  * Revision 3.3  82/11/28  21:36:49  wft
  83.  * 4.2 prerelease
  84.  * 
  85.  * Revision 3.3  82/11/28  21:36:49  wft
  86.  * Replaced ferror() followed by fclose() with ffclose().
  87.  * Putdesc() now suppresses the prompts if stdin
  88.  * is not a terminal. A pointer to the current log message is now
  89.  * inserted into the corresponding delta, rather than leaving it in a
  90.  * global variable.
  91.  *
  92.  * Revision 3.2  82/10/18  21:11:26  wft
  93.  * I added checks for write errors during editing, and improved
  94.  * the prompt on putdesc().
  95.  *
  96.  * Revision 3.1  82/10/13  15:55:09  wft
  97.  * corrected type of variables assigned to by getc (char --> int)
  98.  */
  99.  
  100.  
  101.  
  102.  
  103. #include "rcsbase.h"
  104.  
  105. extern struct hshentry * getnum();
  106. extern FILE * fopen();
  107. extern savestring();
  108. extern editstring();
  109.  
  110. extern int nextc;          /* next character from lexical analyzer          */
  111. extern char Ktext[];       /* keywords from syntax analyzer                 */
  112. extern char Klog[];        /* Keyword "log"                                 */
  113. extern char Kdesc[];       /* Keyword for description                       */
  114. extern FILE * frewrite;    /* new RCS file                                  */
  115. extern FILE * fcopy;       /* result file during editing                    */
  116. extern char * resultfile;  /* file name for fcopy                           */
  117. extern int    rewriteflag; /* indicates whether to rewrite the input file   */
  118. #ifdef MSDOS
  119. extern char tmpdir[NCPPN];
  120. #endif /* MSDOS */
  121.  
  122. char    curlogmsg[logsize]; /* buffer for current log message                */
  123.  
  124. enum stringwork {copy, edit, expand, edit_expand };
  125. /* parameter to scandeltatext() */
  126.  
  127.  
  128.  
  129.  
  130. char * buildrevision(deltas, target, dir, expandflag)
  131. struct hshentry ** deltas, * target;
  132. char * dir; int expandflag;
  133. /* Function: Generates the revision given by target
  134.  * by retrieving all deltas given by parameter deltas and combining them.
  135.  * If dir==nil, the revision is printed on the standard output,
  136.  * otherwise written into a temporary file in directory dir.
  137.  * if expandflag==true, keyword expansion is performed.
  138.  * returns false on errors, the name of the file with the revision otherwise.
  139.  *
  140.  * Algorithm: Copy inital revision unchanged. Then edit all revisions but
  141.  * the last one into it, alternating input and output files (resultfile and
  142.  * editfile). The last revision is then edited in, performing simultaneous
  143.  * keyword substitution (this saves one extra pass).
  144.  * All this simplifies if only one revision needs to be generated,
  145.  * or no keyword expansion is necessary, or if output goes to stdout.
  146.  */
  147. {
  148.         int i;
  149.  
  150.         if (deltas[0]==target) {
  151.                 /* only latest revision to generate */
  152.                 if (dir==nil) {/* print directly to stdout */
  153.                         fcopy=stdout;
  154.                         scandeltatext(target,expand);
  155.                         return(char *) true;
  156.                 } else {
  157.                         initeditfiles(dir);
  158.                         scandeltatext(target,expandflag?expand:copy);
  159.                         ffclose(fcopy);
  160.                         return(resultfile);
  161.                 }
  162.         } else {
  163.                 /* several revisions to generate */
  164. #ifdef MSDOS
  165.                 initeditfiles(dir?dir: tmpdir);
  166. #else
  167.                 initeditfiles(dir?dir:"/tmp/");
  168. #endif /* MSDOS */
  169.                 /* write initial revision into fcopy, no keyword expansion */
  170.                 scandeltatext(deltas[0],copy);
  171.                 i = 1;
  172.                 while (deltas[i+1] != nil) {
  173.                         /* do all deltas except last one */
  174.                         scandeltatext(deltas[i++],edit);
  175.                 }
  176.                 if (!expandflag) {
  177.                         /* no keyword expansion; only invoked from ci */
  178.                         scandeltatext(deltas[i],edit);
  179.                         finishedit((struct hshentry *)nil);
  180.                         ffclose(fcopy);
  181.                 } else {
  182.                         /* perform keyword expansion*/
  183.                         /* first, get to beginning of file*/
  184.                         finishedit((struct hshentry *)nil); swapeditfiles(dir==nil);
  185.                         scandeltatext(deltas[i],edit_expand);
  186.                         finishedit(deltas[i]);
  187.                         if (dir!=nil) ffclose(fcopy);
  188.                 }
  189.                 return(resultfile); /*doesn't matter for dir==nil*/
  190.         }
  191. }
  192.  
  193.  
  194.  
  195. scandeltatext(delta,func)
  196. struct hshentry * delta; enum stringwork func;
  197. /* Function: Scans delta text nodes up to and including the one given
  198.  * by delta. For the one given by delta, the log message is saved into
  199.  * curlogmsg and the text is processed according to parameter func.
  200.  * Assumes the initial lexeme must be read in first.
  201.  * Does not advance nexttok after it is finished.
  202.  */
  203. {       struct hshentry * nextdelta;
  204.  
  205.         do {
  206.                 nextlex();
  207.                 if (!(nextdelta=getnum())) {
  208.                         fatserror("Can't find delta for revision %s", delta->num);
  209.                 }
  210.                 if (!getkey(Klog) || nexttok!=STRING)
  211.                         serror("Missing log entry");
  212.                 elsif (delta==nextdelta) {
  213.                         VOID savestring(curlogmsg,logsize);
  214.                         delta->log=curlogmsg;
  215.                 } else {readstring();
  216.                         delta->log= "";
  217.                 }
  218.                 nextlex();
  219.                 if (!getkey(Ktext) || nexttok!=STRING)
  220.                         fatserror("Missing delta text");
  221.  
  222.                 if(delta==nextdelta)
  223.                         /* got the one we're looking for */
  224.                         switch (func) {
  225.                         case copy:      copystring();
  226.                                         break;
  227.                         case expand:    xpandstring(delta);
  228.                                         break;
  229.                         case edit:      editstring((struct hshentry *)nil);
  230.                                         break;
  231.                         case edit_expand: editstring(delta);
  232.                                         break;
  233.                         }
  234.                 else    readstring(); /* skip over it */
  235.  
  236.         } while (delta!=nextdelta);
  237. }
  238.  
  239.  
  240. int stdinread; /* stdinread>0 if redirected stdin has been read once */
  241.  
  242. int ttystdin()
  243. {
  244.     static int initialized, istty;
  245.     if (!initialized) {
  246.         istty = isatty(fileno(stdin));
  247.         initialized = 1;
  248.     }
  249.     return istty;
  250. }
  251.  
  252. putdesc(initflag,textflag,textfile,quietflag)
  253. int initflag,textflag; char * textfile; int quietflag;
  254. /* Function: puts the descriptive text into file frewrite.
  255.  * if !initflag && !textflag, the text is copied from the old description.
  256.  * Otherwise, if the textfile!=nil, the text is read from that
  257.  * file, or from stdin, if textfile==nil.
  258.  * Increments stdinread if text is read from redirected stdin.
  259.  * if initflag&&quietflag&&!textflag, an empty text is inserted.
  260.  * if !initflag, the old descriptive text is discarded.
  261.  */
  262. {       register FILE * txt; register int c, old1, old2;
  263.     register FILE * frew;
  264. #ifdef lint
  265.     if (quietflag ==  0) initflag = quietflag; /* silencelint */
  266. #endif
  267.  
  268.     frew = frewrite;
  269.         if (!initflag && !textflag) {
  270.                 /* copy old description */
  271.                 VOID fprintf(frew,"\n\n%s%c",Kdesc,nextc);
  272.                 rewriteflag=true; getdesc(false);
  273.         } else {
  274.                 /* get new description */
  275.                if (!initflag) {
  276.                         /*skip old description*/
  277.                         rewriteflag=false; getdesc(false);
  278.                 }
  279.                 VOID fprintf(frew,"\n\n%s\n%c",Kdesc,SDELIM);
  280.                 if (textfile) {
  281.                         old1='\n';
  282.                         /* copy textfile */
  283.                         if ((txt=fopen(textfile,"r"))!=NULL) {
  284.                                 while ((c=getc(txt))!=EOF) {
  285.                                         if (c==SDELIM) VOID putc(c,frew); /*double up*/
  286.                                         VOID putc(c,frew);
  287.                                         old1=c;
  288.                                 }
  289.                                 if (old1!='\n') VOID putc('\n',frew);
  290.                                 VOID fclose(txt);
  291.                 VOID putc(SDELIM,frew);
  292.                 VOID fputs("\n\n", frew);
  293.                 return;
  294.                         } else {
  295.                                 error("Can't open file %s with description",textfile);
  296.                                 if (!ttystdin()) return;
  297.                                 /* otherwise, get description from terminal */
  298.                         }
  299.                 }
  300.                 /* read text from stdin */
  301.                 if (ttystdin()) {
  302. #ifdef MSDOS
  303.                     VOID fputs("enter description, terminated with ^Z or '.':\n",stderr);
  304. #else
  305.                     VOID fputs("enter description, terminated with ^D or '.':\n",stderr);
  306. #endif /* MSDOS */
  307.                     VOID fputs("NOTE: This is NOT the log message!\n>> ",stderr);
  308.             if (feof(stdin))
  309.                     clearerr(stdin);
  310.                 } else {  /* redirected stdin */
  311.                     if (stdinread>0)
  312.                         faterror("Can't reread redirected stdin for description; use -t<file>");
  313.                     stdinread++;
  314.                 }
  315.                 c = '\0'; old2= '\n';
  316.                 if ((old1=getchar())==EOF) {
  317.                         if (ttystdin()) {
  318.                              VOID putc('\n',stderr);
  319.                              clearerr(stdin);
  320.             }
  321.         } else {
  322.              if (old1=='\n' && ttystdin())
  323.              VOID fputs(">> ",stderr);
  324.              for (;;) {
  325.                             c=getchar();
  326.                             if (c==EOF) {
  327.                                     if (ttystdin()) {
  328.                                             VOID putc('\n',stderr);
  329.                                             clearerr(stdin);
  330.                     }
  331.                                     VOID putc(old1,frew);
  332.                                     if (old1!='\n') VOID putc('\n',frew);
  333.                                     break;
  334.                             }
  335.                             if (c=='\n' && old1=='.' && old2=='\n') {
  336.                                     break;
  337.                             }
  338.                             if (c=='\n' && ttystdin()) VOID fputs(">> ",stderr);
  339.                 if(old1==SDELIM) VOID putc(old1,frew); /* double up*/
  340.                 VOID putc(old1,frew);
  341.                             old2=old1;
  342.                             old1=c;
  343.                     } /* end for */
  344.         }
  345.         VOID putc(SDELIM,frew); VOID fputs("\n\n",frew);
  346.         }
  347. }
  348.